`timescale 1ns / 1ps
`include "defines.v"
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2019/11/09 16:05:19
// Design Name: 
// Module Name: id
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module id(
    input wire rst,
    input wire [`InstAddrBus] pc_i,
    input wire [`InstBus] inst_i, 
    //读取的regfile的值
    input wire [`RegBus] reg1_data_i,
    input wire [`RegBus] reg2_data_i,

    //输出到regfile的信息
    output reg reg1_read_o,
    output reg reg2_read_o,
    output reg [`RegAddrBus] reg1_addr_o,
    output reg [`RegAddrBus] reg2_addr_o,
    //送到执行阶段的信息
    output reg [`AluOpBus] aluop_o,//译码阶段的指令要进行的运算的子类型
    output reg [`AluSelBus] alusel_o,//译码阶段的指令要进行的运算的类型
    output reg [`RegBus] reg1_o,//译码阶段要进行的源操作数1
    output reg [`RegBus] reg2_o,//译码阶段要进行的源操作数2
    output reg [`RegAddrBus] wd_o,//译码阶段指令要写入的目的寄存器地址
    output reg wreg_o//译码阶段的指令是否有要写入的目的寄存器
    );

    //取得指令的指令码、功能码
    //对于ori指令只需通过判断第26——31bit的值，即可判断是否是ori指令
    wire [5:0] op = inst_i[31:26];
    wire [4:0] op2 = inst_i[10:6];
    wire [5:0] op3 = inst_i[5:0];
    wire [4:0] op4 = inst_i[20:16];

    //保存指令执行需要的立即数
    reg[`RegBus] imm;
    //指示指令是否有效
    reg instvalid;

    /********************指令译码**************************/
    always @(*) begin
        if (rst == `RstEnable) begin
            aluop_o <= `EXE_NOP_OP;
            alusel_o <= `EXE_RES_NOP;
            wd_o <= `NOPRegAddr;
            wreg_o <= `WriteDisable;
            instvalid <= `InstValid;
            reg1_read_o <= 1'b0;
            reg2_read_o <= 1'b0;
            reg1_addr_o <= `NOPRegAddr;
            reg2_addr_o <= `NOPRegAddr;
            imm <= 32'h0;
        end else begin
            aluop_o <= `EXE_NOP_OP;
            alusel_o <= `EXE_RES_NOP;
            wd_o <= inst_i[15:11];
            wreg_o <= `WriteDisable;
            instvalid <= `InstValid;
            reg1_read_o <= 1'b0;
            reg2_read_o <= 1'b0;
            reg1_addr_o <= inst_i[25:21];
            reg2_addr_o <= inst_i[20:16];
            imm <= `ZeroWord;

            case (op)
                `EXE_ORI: begin
                    //roi指令需要把结果写入目标寄存器
                    wreg_o <= `WriteEnable;
                    //运算的子类型是逻辑‘或’
                    aluop_o <= `EXE_OR_OP;
                    //运算类型是逻辑运算
                    alusel_o <= `EXE_RES_LOGIC;
                    //需要通过refile的读端口1读取寄存器
                    reg1_read_o <= 1'b1;
                    //不需要读regfile的端口2
                    reg2_read_o <= 1'b0;
                    //指令执行需要立即数
                    imm <= {16'h0, inst_i[15:0]};
                    //指令执行需要写
                    wd_o <= inst_i[20:16];
                    //ori是有效指令
                    instvalid <= `InstValid;
                end
                default: begin
                    
                end
            endcase 

        end
    end


    /*****************确定进行运算的源操作数1****************/
    always @(*) begin
        if (rst == `RstEnable) begin
            reg1_o <= `ZeroWord;
            // reg2_o <= `ZeroWord;
        end
        else if (reg1_read_o == 1'b1) begin
                reg1_o <= reg1_data_i; //regfile读端口1的内容
        end
        else if (reg1_read_o == 1'b0) begin
                reg1_o <= imm;
        end
    end 


    /*****************确定进行运算的源操作数2**********************/
    always @(*) begin
        if (rst == `RstEnable) begin
            reg2_o <= `ZeroWord;
            // reg2_o <= `ZeroWord;
        end
        else if (reg2_read_o == 1'b1) begin
                reg2_o <= reg2_data_i; //regfile读端口1的内容
        end
        else if (reg2_read_o == 1'b0) begin
                reg2_o <= imm;
        end
    end

endmodule
